package com.yawn.zddefect.service;

import com.yawn.zddefect.controller.entity.RestResponse;
import com.yawn.zddefect.entity.Defect;
import com.yawn.zddefect.entity.Project;
import com.yawn.zddefect.project.ProjectService;
import com.yawn.zddefect.util.ActivitiUtil;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.identity.User;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.transaction.Transactional;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.yawn.zddefect.util.Constant.PD_KEY_ZERO_DEFECT;

/**
 * @author Created by yawn on 2018-01-30 18:38
 */
@Service
@Transactional
public class DefectService {

    @Resource
    private RuntimeService runtimeService;
    @Resource
    private IdentityService identityService;
    @Resource
    private TaskService taskService;

    @Resource
    private ProjectService projectService;

    private int id = 0;

    public RestResponse startDefect(String userId, Defect defect) {
        identityService.setAuthenticatedUserId(userId);
        ProcessInstance instance = runtimeService.startProcessInstanceByKey(PD_KEY_ZERO_DEFECT);
        Task task = taskService.createTaskQuery().processInstanceId(instance.getId()).singleResult();
        String taskId = task.getId();
        taskService.claim(taskId, userId);
        Map<String, Object> vars = new HashMap<>();
        String projectId = defect.getProjectId();
        vars.put("code", generateCode(projectId));
        vars.put("projectId", projectId);
        vars.put("rank", defect.getRank());
        vars.put("content", defect.getContent());
        vars.put("attachmentList", defect.getAttachmentList());
        taskService.complete(taskId, vars);
        // 默认将下一步的处理人设置为项目负责人
        Task nextTask = taskService.createTaskQuery().processInstanceId(instance.getId()).singleResult();
        taskService.setAssignee(nextTask.getId(), projectService.findOne(projectId).getManager());
        return RestResponse.newInstance(1);
    }

    public RestResponse todoTask(String userId) {
        List<Task> taskList = taskService.createTaskQuery()
                .processDefinitionKey(PD_KEY_ZERO_DEFECT)
                .taskAssignee(userId)
                .orderByTaskName().asc()
                .orderByTaskCreateTime().desc()
                .list();
        List<Defect> defectList = new ArrayList<>();
        for (Task task : taskList) {
            Map<String, Object> variables = runtimeService.getVariables(task.getExecutionId());
            Defect defect = new Defect();
            defect.setTaskId(task.getId());
            defect.setTaskName(task.getName());
            ActivitiUtil.setVars(defect, variables);
            defectList.add(defect);
        }
        return RestResponse.newInstance(1, defectList);
    }

    public RestResponse setAssignee(String userId, Defect defect) {
        String taskId = defect.getTaskId();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if (!"处理缺陷".equals(task.getName())) {
            return RestResponse.newInstance(0, "无法为此任务设置处理人！", task.getName());
        }
        if (userId.equals(task.getAssignee())) {
            taskService.setAssignee(taskId, defect.getAssignee());
        } else {
            return RestResponse.newInstance(0, "你无权设置处理人！");
        }
        return RestResponse.newInstance(1);
    }

    public RestResponse doTask(String userId, Defect defect) {
        String taskId = defect.getTaskId();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        taskService.claim(taskId, userId);
        taskService.setAssignee(taskId, userId);

        Map<String, Object> vars = new HashMap<>();
        vars.put("completed", defect.isCompleted());
        vars.put("assignee", userId);
        taskService.complete(taskId, vars);

        if (!defect.isCompleted()) {
            // 开发组完成或要求修改
            if ("处理缺陷".equals(task.getName())) {
                String processInstanceId = task.getProcessInstanceId();
                ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
                Task nextTask = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
                taskService.setAssignee(nextTask.getId(), processInstance.getStartUserId());
            }
//            // 测试组结束问题或要求重新解决问题
//            else {
//                // TODO 流程回到重新解决问题这里Assignee是否会改变
//            }
        }
        return RestResponse.newInstance(1);
    }

    public RestResponse reviseDefect(String userId, Defect defect) {
        String taskId = defect.getTaskId();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        taskService.claim(taskId, userId);
        boolean completed = defect.isCompleted();
        Map<String, Object> vars = new HashMap<>();
        vars.put("completed", completed);
        if (!completed) {
            vars.put("rank", defect.getRank());
            vars.put("content", defect.getContent());
            vars.put("attachmentList", defect.getAttachmentList());
        }
        taskService.complete(taskId, vars);
        if (!completed) {
            Task nextTask = taskService.createTaskQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
            String assignee = runtimeService.getVariable(task.getExecutionId(), "assignee", String.class);
            taskService.setAssignee(nextTask.getId(), assignee);
        }
        return RestResponse.newInstance(1);
    }

    private String generateCode(String projectId) {
        Project project = projectService.findOne(projectId);
        String proSN = project.getSn();
        LocalDate dateTime = LocalDate.now();
        String year = String.format("%04d", dateTime.getYear());
        String dayOfYear = String.format("%04d", dateTime.getDayOfYear());
        String increase = String.format("%04d", ++id);
        return proSN + year.substring(2) + dayOfYear + increase;
    }

    public RestResponse addComment(String userId, String taskId, String comment) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        identityService.setAuthenticatedUserId(userId);
        taskService.addComment(taskId, task.getProcessInstanceId(), comment);
        return RestResponse.newInstance(1);
    }

    public RestResponse getProcessInstanceComment(String taskId) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        return getComment(task.getProcessInstanceId());
    }

    public RestResponse getComment(String processInstanceId) {
        List<Comment> commentList = taskService.getProcessInstanceComments(processInstanceId);
        return RestResponse.newInstance(1, commentList);
    }

    public void addAttachment(String taskId, String attachName) {
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        List attachmentList = (List<String>)runtimeService.getVariable(task.getExecutionId(), "attachmentList", List.class);
        attachmentList.add(attachName);
        runtimeService.setVariable(task.getExecutionId(), "attachmentList", attachmentList);
    }
}
